package com.sky.business.sys.service.impl;

import com.sky.business.sys.domain.AlarmRecord;
import com.sky.business.sys.service.AlarmRecordService;
import com.sky.business.sys.service.NVRDeviceService;
import com.sky.common.enums.AlarmRecordNvrStatus;
import com.sky.common.exception.FFmpegException;
import com.sky.common.exception.NoPicException;
import com.sky.common.utils.DateUtils;
import com.sky.common.utils.MinIOUploader;
import com.sky.common.utils.MinioConstants;
import com.sky.common.utils.NVRClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class NVRDeviceServiceImpl implements NVRDeviceService {

    @Autowired
    private AlarmRecordService alarmRecordService;

    @Override
    @Async("alarmRecordExecutor")
    public void processAlarmNvr(AlarmRecord alarmRecord) {
        try {
            String videoUrl = downloadRecordByTime(alarmRecord.getChannelno(),alarmRecord.getBeginTime(),alarmRecord.getEndTime());
            alarmRecord.setVideoUrl(videoUrl);
            alarmRecord.setVideoStatus(AlarmRecordNvrStatus.SUCCESS);
            alarmRecordService.updateById(alarmRecord);
        } catch (Exception e) {
            alarmRecord.setVideoStatus(AlarmRecordNvrStatus.FAILED);
            alarmRecordService.updateById(alarmRecord);
            log.error("获取nvr视频发生异常",e);
        }
        try {
            String imageUrl = downloadCatchPicByTime(alarmRecord.getChannelno(),alarmRecord.getBeginTime(),alarmRecord.getEndTime());
            alarmRecord.setImageUrl(imageUrl);
            alarmRecord.setImageStatus(AlarmRecordNvrStatus.SUCCESS);
            alarmRecordService.updateById(alarmRecord);
        } catch (IOException e) {
            alarmRecord.setImageStatus(AlarmRecordNvrStatus.FAILED);
            alarmRecordService.updateById(alarmRecord);
            log.error("获取nvr图片发生异常",e);
        }
    }

    @Override
    public String downloadRecordByTime(int channelNo, Date startTime, Date endTime) throws InterruptedException, IOException {

        String videoUrl = null;

        //从NVR下载录像到本地
        String videoPath = NVRClientUtil.downloadVideoRecordByTime(channelNo, startTime, endTime);

        //调用ffmpeg将MP4的文件索引从文件末尾放到文件开头
        String[] videoPathArray = videoPath.split("\\.");
        String outputPath = videoPathArray[0] + "_trans." + videoPathArray[1];

        // FFmpeg 命令
        String command = String.format("ffmpeg -i %s -movflags faststart -c copy %s", videoPath, outputPath);

        try {
            // 创建进程
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();

            // 输出 FFmpeg 的日志
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    log.info(line);
                }
            }

            // 等待进程完成
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                log.info("成功将 moov 信息移动到文件开头: " + outputPath);
            } else {
                log.error("FFmpeg 执行失败，退出代码: " + exitCode);
                throw new FFmpegException("500", "FFmpeg 执行失败，退出代码: " + exitCode);
            }

            String objectName = UUID.randomUUID().toString().replace("-", "");

            objectName = objectName +"."+ videoPathArray[1];
            // 从本地上传到Minio对象存储
            videoUrl = MinIOUploader.uploadFile(MinioConstants.MINIO_BUCKET_NAME, objectName, outputPath);
        } catch (IOException | InterruptedException e) {
            log.error("FFmpeg 执行失败", e);
            throw new FFmpegException("500", "FFmpeg 执行失败");
        }finally {
            // 删除本地文件
            Path path = Paths.get(videoPath);
            Files.delete(path);

            Path path2 = Paths.get(outputPath);
            Files.delete(path2);
        }

        return videoUrl;
    }

    @Override
    public String downloadCatchPicByTime(int channelNo, Date startTime, Date endTime) throws IOException {
        List<String> picPathList;
        try {
            picPathList = NVRClientUtil.downloadPictureByTime(channelNo, startTime, endTime);
        }catch (NoPicException e){
            log.error(e.getMessage());
            return null;
        }
        int num = picPathList.size() / 2;
        //取中间一张
        String picPath = picPathList.get(num);

        String objectName = UUID.randomUUID().toString().replace("-", "");
        String suffix = picPath.substring(picPath.lastIndexOf("."));
        objectName = objectName + suffix;
        String picUrl = MinIOUploader.uploadFile(MinioConstants.MINIO_BUCKET_NAME, objectName, picPath);

        return picUrl;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        NVRDeviceServiceImpl nvrDeviceService = new NVRDeviceServiceImpl();
        NVRClientUtil.init();
//        String url =  nvrDeviceService.downloadRecordByTime(7, DateUtils.from(LocalDateTime.of(2025,6,30, 14, 54, 0)),
//                DateUtils.from(LocalDateTime.of(2025,6,30, 14, 56, 0)));
//        System.out.println(url);
        String picUrl = nvrDeviceService.downloadCatchPicByTime(7, DateUtils.from(LocalDateTime.of(2025,6,30, 14, 54, 0)),
                DateUtils.from(LocalDateTime.of(2025,6,30, 14, 56, 0)));

        System.out.println(picUrl);
    }



}
